package com.foldingleaf.app.login.controller;


import com.foldingleaf.app.login.service.SendSms;

import com.foldingleaf.common.constant.Constants;
import com.foldingleaf.common.core.domain.Result;
import com.foldingleaf.common.core.domain.entity.SysUser;
import com.foldingleaf.common.core.domain.model.LoginUser;
import com.foldingleaf.common.core.redis.RedisCache;
import com.foldingleaf.common.exception.ServiceException;
import com.foldingleaf.common.exception.user.UserPasswordNotMatchException;
import com.foldingleaf.common.utils.*;
import com.foldingleaf.common.utils.ip.IpUtils;
import com.foldingleaf.framework.manager.AsyncManager;
import com.foldingleaf.framework.manager.factory.AsyncFactory;
import com.foldingleaf.framework.web.service.SmsCodeAuthenticationToken;
import com.foldingleaf.framework.web.service.SysLoginService;
import com.foldingleaf.framework.web.service.TokenService;
import com.foldingleaf.system.service.ISysUserService;

import io.swagger.annotations.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Api("/login")
@RestController
@CrossOrigin    //跨域支持
@RequestMapping(value = "/login")
public class SmsApiController {

    @Autowired
    private SendSms sendSms;

    @Autowired
    private RedisCache redisCache;
    private  long expire = 60*60*24*7;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private ISysUserService iuserService;

    @Resource
    private AuthenticationManager authenticationManager;
    /**
     * @param telephone 手机号
     * @name: 发送验证码
     * @return: com.fodingleaf.zdsl.result.Result<java.lang.Object>
     * */




    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "string", name = "telephone", value = "手机号")
    })
    @ApiOperation(value = "登录--发送短信", notes = "发送短信", httpMethod = "GET")
    @GetMapping("/SendSms")
    public Result code(@ApiParam(name = "telephone",value = "手机号") String telephone, HttpServletRequest request, @RequestHeader(value = "platform",required = false) String platform,@RequestHeader(value = "version",required = false) String version,@RequestHeader(value = "date",required = false) String date) throws Exception{

        if (platform==null||platform.equals("")){
             return Result.error("请先下载软件,如在软件操作请联系邮箱");
        }
        if (version==null||version.equals("")){
            return Result.error(500,"请先更新版本");
        }
        if(!version.equals("1.0.7")){
          return  Result.error(500,"请先更新版本");
        }

        System.out.println("platform:"+platform);
        //从Redis中获取手机号对应验证码
        String code = redisCache.getCacheObject(Constants.CAPTCHA_CODE_KEY+telephone);

        //如果获取的验证码不为空，说明已经存在，至于这里我为什么使用Map后面会解释。
        if(!StringUtils.isEmpty(code)){
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("message","验证码已存在,还没有过期");
            map.put("data",code);
            //用Fastjson转为json返回
            return Result.error("请等待一分钟后重试～");
        }





        // TODO: 2022/6/18 注释注册
//        //到了这里说明手机号获得的验证码为空，生成验证码并存储到Redis中
           HashMap<String,Object> param = new HashMap<>();
//        //随机
//
       code = String.valueOf((int)((Math.random()*9+1)*1000));


        //测试
        if (telephone.equals("18822222222")){
            code = "1234";
        }

        param.put("code",code);

        System.out.println("短信验证码:"+code);

        // TODO: 2022/6/18  注释注册
        //调用发送验证码方法，将发送的手机号，短信模板，以及验证码传入
        boolean isSend = sendSms.send(telephone, "SMS_229810318", param);
        //冒泡算法



        //如果发送成功，则将手机号和验证码存入Redis,设置为2分钟后过期
     if(isSend){
         redisCache.setCacheObject(Constants.CAPTCHA_CODE_KEY+telephone,code,1, TimeUnit.MINUTES);
            return Result.success("验证码发送成功！一分钟内有效");
        }else{

         return Result.error("验证码发送失败");
        }


    }
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "string", name = "telephone", value = ""),
            @ApiImplicitParam(paramType = "query", dataType = "string", name = "code", value = ""),
            @ApiImplicitParam(paramType = "query", dataType = "boolean", name = "inv", value = "是否邀请 网页使用参数"),
            @ApiImplicitParam(paramType = "query", dataType = "string", name = "inkCode", value = "邀请人邀请码 网页使用参数")
    })
    @ApiOperation(value = "登录--验证ww", notes = "短信验证", httpMethod = "GET")
    @GetMapping("/Verification")

    public Result verification(@ApiParam(name = "telephone",value = "手机号") String telephone, @ApiParam(name = "code",value = "短信验证码")  String code,boolean inv,String inkCode) throws Exception{
        Result ajax = Result.success();
        //从Redis中获取手机号对应验证码
        String cacheCode  =redisCache.getCacheObject(Constants.CAPTCHA_CODE_KEY+telephone);
        //如果获取的验证码不为空，说明已经存在，至于这里我为什么使用Map后面会解释。
        if(!StringUtils.isEmpty(cacheCode)){
            if(code.equals(cacheCode)){
                // 用户验证
                Authentication authentication = null;
                try
                {
                    // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername（这块调用了UserDetailsServiceImpl的loadUserByUsername）
                    authentication = authenticationManager
                            .authenticate(new SmsCodeAuthenticationToken(telephone, code));

                }
                catch (Exception e)
                {
                    if (e instanceof BadCredentialsException)
                    {
                        AsyncManager.me().execute(AsyncFactory.recordLogininfor(telephone, null,Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
                        throw new ServiceException("验证码错误");
                    }

                }
                LoginUser loginUser = (LoginUser) authentication.getPrincipal();
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(telephone,  Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
                recordLoginInfo(loginUser.getUserId());
                String token =   tokenService.createToken(loginUser);
                Map<String, Object> map = new HashMap<>();
                map.put(Constants.TOKEN, token);

            ///网页使用
            if (inv) {
                SysUser sysUser = iuserService.selectUserById(loginUser.getUserId());
                sysUser.setInviteCodeByUserId(inkCode);
                sysUser.setRemark("用户");
                iuserService.updateUser(sysUser);

            }

                return Result.success(map);




            }else {

                return Result.error("验证码错误！");
            }

        }
        return Result.error("验证码错误！");
    }

    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "string", name = "telephone", value = ""),
            @ApiImplicitParam(paramType = "query", dataType = "string", name = "password", value = "")
    })
    @ApiOperation(value = "登录-账号密码登录", notes = "账号密码登录", httpMethod = "GET")
    @GetMapping("/PasswordLogin")
    public Result passwordLogin(@ApiParam(name = "telephone",value = "手机号") String telephone, @ApiParam(name = "password",value = "密码")  String password) throws Exception{
//        Result ajax = Result.success();
//        // 用户验证
//        Authentication authentication = null;
//        try
//        {
//            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
//            authentication = authenticationManager
//                    .authenticate(new UsernamePasswordAuthenticationToken(telephone, password));
//
//        }
//        catch (Exception e)
//        {
//            if (e instanceof BadCredentialsException)
//            {
//                AsyncManager.me().execute(AsyncFactory.recordLogininfor(telephone, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
//                throw new UserPasswordNotMatchException();
//            }
//            else
//            {
//                AsyncManager.me().execute(AsyncFactory.recordLogininfor(telephone, Constants.LOGIN_FAIL, e.getMessage()));
//                throw new ServiceException(e.getMessage());
//            }
//        }
//        AsyncManager.me().execute(AsyncFactory.recordLogininfor(telephone, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
//        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
//        recordLoginInfo(loginUser.getUserId());
//        // 生成token
//        String token =  tokenService.createToken(loginUser);
//        Map<String, Object> map = new HashMap<>();
//        map.put(Constants.TOKEN, token);
//
//
//        return Result.success(map);
        return  Result.success();

    }


    /**
     * 获取登录用户信息
     */
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "HttpServletRequest", name = "request", value = "")
    })
    @ApiOperation(value = "获取登录用户信息", notes = "获取登录用户信息", httpMethod = "GET")
    @GetMapping("/loginUser")
    public Result loginUser(HttpServletRequest request,@RequestHeader(value = "version",required = false) String version)  {

        SysUser sysUser = iuserService.selectUserById(SecurityUtils.getLoginUser().getUserId());


        if (sysUser == null)
            return Result.error("用户未登录");

        return Result.success(sysUser);
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "long", name = "userId", value = "用户ID")
    })
    @ApiOperation(value = "记录登录信息", notes = "记录登录信息")
    public void recordLoginInfo(Long userId)
    {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        sysUser.setLoginDate(DateUtils.getNowDate());
        iuserService.updateUserProfile(sysUser);
    }
}



